package easytalk.views;


import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.part.ViewPart;

import common.Discussion;
import common.DiscussionState;
import common.EasyChatEnvironment;
import common.Locutor;

import connection.ServerConnectionConfig;
import easytalk.dialogs.AuthDialog;
import easytalk.dialogs.ChatDialogManager;
import easytalk.media.EasyTalkImages;
import easytalk.views.custom.ConnectionProgress;
import easytalk.views.custom.MessageEditor;

public class FriendListView extends ViewPart {
	public static final String ID = Messages.getString("FriendListView.0"); //$NON-NLS-1$
	
	
	/**********************************/
	/*			actions				  */
	/**********************************/
	private Action connectionAction;
	private Action showOfflineAction;
	private Action doubleClickAction;
	private List<Action> savedConnection = new ArrayList<Action>();
	private long displayVersion = 0;

	/*********************************/
	/*		Grapical components		*/
	/*********************************/
	private Table friendTable;
	private TableViewer viewer;
	private MessageEditor imText;
	private FormToolkit toolkit;
	private Form form;
	private Section messageSection;
	private Section friendSection;
	private Section serversSection;
	private Composite serversComposite;
	private Section wallSection;
	private TableViewer serverListViewer;
	private boolean showOffine = false;
	
	/**
	 * The constructor.
	 */
	public FriendListView() {

	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		fillLocalToolBar(bars.getToolBarManager());
	}

	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {

		ChatDialogManager.getInstance().setDisplay(parent.getDisplay());
		ChatDialogManager.getInstance().start();

		toolkit = new FormToolkit(parent.getDisplay());

		form = toolkit.createForm(parent);

		GridLayout gridLayout = new GridLayout(1, true);
		gridLayout.marginWidth = 5;
		gridLayout.marginHeight = 5;
		gridLayout.verticalSpacing = 0;
		gridLayout.horizontalSpacing = 0;
		form.getBody().setLayout(gridLayout);
		form.getBody().setLayoutData(
				new GridData(SWT.FILL, SWT.FILL, true, true));

		serversSection = toolkit.createSection(form.getBody(),
				Section.TITLE_BAR | Section.TWISTIE);
		serversSection.setText(Messages.getString("FriendListView.1")); //$NON-NLS-1$
		serversSection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				false, 1, 1));

		serversComposite = new Composite(serversSection, SWT.WRAP);
		serversComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				false));
		serversComposite.setLayout(new GridLayout(1, false));

		Table table = toolkit.createTable(serversComposite, SWT.BORDER);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		serverListViewer = new TableViewer(table);
		serverListViewer.setLabelProvider(new ServerLaberProvider());
		serverListViewer.setContentProvider(new ServerContentProvider());
		serverListViewer.setInput(EasyChatEnvironment.getInstance());
		
		serversSection.setClient(serversComposite);

		friendSection = toolkit.createSection(form.getBody(), Section.TWISTIE
				| Section.DESCRIPTION | Section.TITLE_BAR);
		friendSection.setText("Friend list"); //$NON-NLS-1$
		friendSection.setDescription(Messages.getString("FriendListView.2")); //$NON-NLS-1$
		friendSection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				true, 1, 1));

		Composite composite = toolkit.createComposite(friendSection, SWT.WRAP);
		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		composite.setLayout(new GridLayout(1, false));

		friendTable = toolkit.createTable(composite, SWT.BORDER | SWT.CHECK | SWT.V_SCROLL | SWT.H_SCROLL);
		friendTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		
		FontData fData = new FontData("Verdana",10,SWT.ITALIC);
		friendTable.setFont(new Font(parent.getShell().getDisplay(),fData));
		
		for (int i = 0; i < 3; i++) {
			TableColumn tc = new TableColumn(friendTable, SWT.LEFT | SWT.BORDER
					| SWT.CHECK);

			tc.setText(Messages.getString("FriendListView.3") + i); //$NON-NLS-1$
			tc.setWidth((i == 0) ? 20 : ((i == 1) ? 20 : 20));
			
			tc.setResizable(false);
		}
		// table.addListener(eventType, listener)

		viewer = new TableViewer(friendTable);
		viewer.setContentProvider(new FriendViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		viewer.setSorter(new NameSorter());
		viewer.addFilter(new FriendListFilter());
		viewer.setInput(EasyChatEnvironment.getInstance());

		friendTable.addListener(SWT.Selection, new Listener() {
			@Override
			public void handleEvent(Event event) {
				if (event.detail == SWT.CHECK) {
					updateCheckState();
				}
			}

		});

		friendSection.setClient(composite);

		messageSection = toolkit.createSection(form.getBody(),
				Section.TITLE_BAR | Section.TWISTIE | Section.DESCRIPTION);
		messageSection.setText("Instant messages"); //$NON-NLS-1$
		messageSection.setDescription(Messages.getString("FriendListView.4")); //$NON-NLS-1$
		messageSection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				false));
		messageSection.setExpanded(false);

		imText = new MessageEditor(messageSection, SWT.SINGLE | SWT.LEAD
				| SWT.BORDER, toolkit);
		imText.getComposite().setLayoutData(
				new GridData(SWT.FILL, SWT.FILL, true, false));
		imText.setText(Messages.getString("FriendListView.5")); //$NON-NLS-1$

		messageSection.setClient(imText.getComposite());

		wallSection = toolkit.createSection(form.getBody(), Section.TITLE_BAR
				| Section.TWISTIE);
		wallSection.setText(Messages.getString("FriendListView.6")); //$NON-NLS-1$
		wallSection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		messageSection.setExpanded(false);
		Composite wallComposite = toolkit
				.createComposite(wallSection, SWT.WRAP);
		wallComposite.setLayout(new GridLayout(1, true));
		Browser browser = new Browser(wallComposite, SWT.BORDER);
		browser.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		
		wallSection.setClient(wallComposite);

		// Create the help context id for the viewer's control
		PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(),
				Messages.getString("FriendListView.7")); //$NON-NLS-1$

		makeActions();
		hookContextMenu();
		hookDoubleClickAction();
		contributeToActionBars();
		createTimerEventes();
		createChatActions();

		parent.addListener(SWT.Activate | SWT.Resize, new Listener() {
			public void handleEvent(Event e) {
				updateCheckState();
				updateColumnSize();
			}
		});
	}

	private void createChatActions() {
		imText.addKeyListener(new KeyListener() {

			@Override
			public void keyPressed(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void keyReleased(KeyEvent e) {
				if ((e.keyCode == 13) || (e.keyCode == 16777296)) {
					String toBeSent = imText.getText();
					for (TableItem item : friendTable.getItems()) {
						if (item.getChecked()) {
							Locutor locutor = (Locutor) item.getData();
							locutor.sendFastMessage(toBeSent);
						}
					}
					imText.setText("");
				} 
				
			}
			
		});
		
	}

	private void createTimerEventes() {

		Display.getCurrent().timerExec(100, new Runnable() {
			@Override
			public void run() {
				long version = EasyChatEnvironment.getVersion();
				if (displayVersion < version) {
					displayVersion = version;
					refreshView();
				}
				Display.getCurrent().timerExec(100, this);
			}

		});

	}

	private void fillContextMenu(IMenuManager manager) {
		manager.add(connectionAction);
		manager.add(showOfflineAction);
		
		for (Action action : savedConnection) {
			manager.add(action);
		}
		// Other plug-ins can contribute there actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}

	private void fillLocalPullDown(IMenuManager manager) {
		manager.add(connectionAction);
		manager.add(new Separator());
		manager.add(showOfflineAction);
		manager.add(new Separator());
		for (Action action : savedConnection) {
			manager.add(action);
		}
	}

	private void fillLocalToolBar(IToolBarManager manager) {
		manager.add(connectionAction);
		manager.add(showOfflineAction);
		
		for (Action action : savedConnection) {
			manager.add(action);
		}
	}

	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager(Messages.getString("FriendListView.8")); //$NON-NLS-1$
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				FriendListView.this.fillContextMenu(manager);
			}
		});
		Menu menu = menuMgr.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, viewer);
	}

	private void hookDoubleClickAction() {
		viewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				doubleClickAction.run();
			}
		});
	}

	private void makeActions() {
		List<ServerConnectionConfig> configs = ServerConnectionConfig.loadAllConfig();
		if (configs!=null)
		for (final ServerConnectionConfig confg : configs) {
			Action action = new Action() { 
				@Override
				public void run() {
					ConnectionProgress progress = new ConnectionProgress(confg);
					progress.init(PlatformUI.getWorkbench().getActiveWorkbenchWindow());
					progress.run(null);
					super.run();
				}
			};
			action.setText(confg.getServerType().name()+":"+confg.getUserName());
			this.savedConnection.add(action);
			
		}
		connectionAction = new Action() {
			public void run() {

				AuthDialog dialog = new AuthDialog(getSite().getShell());
				dialog.open();
				if (dialog.getReturnCode() == Window.CANCEL)
					return;

			}
		};
		connectionAction.setText(Messages.getString("FriendListView.9")); //$NON-NLS-1$
		connectionAction.setToolTipText(Messages.getString("FriendListView.10")); //$NON-NLS-1$
		connectionAction.setImageDescriptor(ImageDescriptor
				.createFromImage(EasyTalkImages.EARTH_CONNECTION));

		showOfflineAction = new Action() {
			public void run() {
				if (showOffine) {
					showOfflineAction.setText(Messages.getString("FriendListView.11")); //$NON-NLS-1$
				}
				else
				{
					showOfflineAction.setText(Messages.getString("FriendListView.12")); //$NON-NLS-1$
				}
				showOfflineAction.setChecked(true);
				showOffine = !showOffine;
				refreshView();
			}
		};
		showOfflineAction.setText(Messages.getString("FriendListView.13")); //$NON-NLS-1$
		showOfflineAction.setToolTipText(Messages.getString("FriendListView.14")); //$NON-NLS-1$
		showOfflineAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
				.getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));
		doubleClickAction = new Action() {
			public void run() {
				ISelection selection = viewer.getSelection();
				Object obj = ((IStructuredSelection) selection)
						.getFirstElement();

				Locutor locutor = (Locutor) obj;
				Discussion discussion = EasyChatEnvironment.getInstance().createDiscussion(null);
				discussion.addLocutor(locutor);
				discussion.setState(DiscussionState.OPEN_WAITING);
				EasyChatEnvironment.getInstance().addDiscussion(discussion);
				ChatDialogManager.getInstance().updateDialogs();
				//
				// easyTalkConnection.OpenChat((BodyChat) obj);
				// ChatDialogManager.getChatDialog((BodyChat)
				// obj).openInANewthread();
				/*
				 * try { //
				 * getSite().getWorkbenchWindow().getActivePage().openEditor(new
				 * ChatInput((BodyChat) obj,easyTalkConnection), ChatEditor.ID);
				 * } catch (PartInitException e) { // TODO Auto-generated catch
				 * block e.printStackTrace(); }
				 */
			}
		};
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {

		// viewer.getControl().setFocus();
	}

	private void showMessage(String message) {
		MessageDialog.openInformation(viewer.getControl().getShell(),
				Messages.getString("FriendListView.15"), message); //$NON-NLS-1$
	}

	/**
	 * Updating views after checking / unchecking items
	 */
	protected void updateCheckState() {
		boolean oneChecked = false;
		for (TableItem item : friendTable.getItems()) {
			if (item.getChecked() == true) {
				oneChecked = true;
				break;
			}
		}

		messageSection.setExpanded(oneChecked);
	}

	/**
	 * updates column size at the friend list viewer
	 */
	protected void updateColumnSize() {

		TableColumn[] columns = friendTable.getColumns();
		int width = friendTable.getBounds().width;
		columns[0].setWidth(width / 3);
		columns[1].setWidth(width / 3);
		columns[2].setWidth(width / 3);
	}

	/**
	 * refresh element at the view
	 */
	protected void refreshView() {
		viewer.refresh();
		serverListViewer.refresh();
		form.layout();
	}

	public void setShowOffine(boolean showOffine) {
		this.showOffine = showOffine;
	}

	public boolean isShowOffine() {
		return showOffine;
	}

}